package com.example.xiaoshuo_yudu.service.impl;

import com.example.xiaoshuo_yudu.entity.dto.BookmarkDto;
import com.example.xiaoshuo_yudu.entity.entity.Books;
import com.example.xiaoshuo_yudu.entity.entity.Bookshelf;
import com.example.xiaoshuo_yudu.mapper.BooksMapper;
import com.example.xiaoshuo_yudu.mapper.BookshelfMapper;
import com.example.xiaoshuo_yudu.mapper.ChapterTablesMapper;
import com.example.xiaoshuo_yudu.service.BooksService;
import com.example.xiaoshuo_yudu.service.BookshelfService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.xiaoshuo_yudu.utils.Const;
import com.google.common.base.Function;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户书架表 服务实现类
 * </p>
 *
 * @author xusen
 * @since 2025-07-31
 */
@Service
public class BookshelfServiceImpl extends ServiceImpl<BookshelfMapper, Bookshelf> implements BookshelfService {
@Autowired
private BookshelfMapper bookshelfMapper;
@Autowired
private BooksMapper booksMapper;
@Autowired
private ChapterTablesMapper chapterTablesMapper;
@Autowired
private RedisTemplate redisTemplate;
    // 锁对象（防止缓存击穿的并发问题）
    private final ReentrantLock lock = new ReentrantLock();
    /**
     * 添加到书架
     *
     * @param userId
     * @param request
     */
    @Override
    public String addBookmark(Long userId, BookmarkDto request) {
        String key = Const.BOOKS_SHELF_DATA + ":" + userId;
        if(userId==null)
            throw new RuntimeException("请先登录");
        Long bookId = request.getBookId();
        Bookshelf existing = bookshelfMapper.selectByUserAndBook(userId, bookId);
        if (existing != null) {
            // 已存在：执行更新（更新章节、位置、最后阅读时间等）
            existing.setChapterId(request.getChapterId()); // 更新当前章节
            existing.setReadProgress(request.getPosition().intValue()); // 更新阅读位置
            existing.setLastRead(LocalDateTime.now()); // 更新最后阅读时间
            // 可选：更新书架状态
            if(existing.getIsBookshelf()==0L){
                existing.setIsBookshelf(0L);
            }
            else if(existing.getIsBookshelf()==1L){
                if(request.getIsBookshelf()==0L)
                    existing.setIsBookshelf(0L);
            }
            boolean updated = this.updateById(existing); // 用已有id执行更新
            if (updated) {
                redisTemplate.delete(key);
                redisTemplate.delete(Const.BOOKS_READING_DATA + ":" + userId);

            }
//   删除缓存

            if (!updated) {
                throw new RuntimeException("更新书架失败");
            }
        } else {
            // 不存在：执行新增
            Bookshelf newBook = new Bookshelf().builder()
                    .userId(userId)
                    .bookId(bookId)
                    .chapterId(request.getChapterId())
                    .readProgress(request.getPosition().intValue())
                    .addTime(LocalDateTime.now())
                    .lastRead(LocalDateTime.now())
                    .isBookshelf(request.getIsBookshelf())
                    .build();
            boolean saved = this.save(newBook);
            if (saved) {
                redisTemplate.delete( key);
                redisTemplate.delete(Const.BOOKS_READING_DATA + ":" + userId);
            }
            if (!saved) {
                throw new RuntimeException("添加书架失败");
            }
        }
        return null;
    }

    /**
     * 获取书架
     *
     * @param userId
     * @return
     */
    @Override
    public List<Map<String, Object>> getBookshelf(Long userId) {
        String key = Const.BOOKS_SHELF_DATA + ":" + userId;
        if(redisTemplate.hasKey(key)){
            Object value = redisTemplate.opsForValue().get(key);
            if (value == null) {
                // 缓存存在但值为null（已处理过穿透），直接返回空列表
                return Collections.emptyList();
            }
            return (List<Map<String, Object>>) value;
        }
        try {
        lock.lock();
        if(redisTemplate.hasKey(key)){
            Object value = redisTemplate.opsForValue().get(key);
            if (value == null) {
                // 缓存存在但值为null（已处理过穿透），直接返回空列表
                return Collections.emptyList();
            }
            return (List<Map<String, Object>>) value;
        }
        ArrayList<Map<String, Object>> list = new ArrayList<>();
        List<Bookshelf> bookshelf=bookshelfMapper.getBookshelf(userId);

//n+1问题      后期优化
        for (Bookshelf bookshelf1 : bookshelf) {
            Integer bookId = bookshelf1.getBookId().intValue();
            if(bookId==null){
                continue;
            }
            Books books = booksMapper.selectById(bookId);
            if (books == null) {
                continue;
            }
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("bookId",bookId);
            hashMap.put("category", books.getCategory());
            hashMap.put("id", bookshelf1.getId());
            hashMap.put("name", books.getNovelName());
            hashMap.put("latestChapter", books.getLatestChapter());
            hashMap.put("author", books.getAuthor());
            hashMap.put("readTime",bookshelf1.getLastRead() );
            hashMap.put("updateTime", books.getUpdateTime());
            Long chapterId = bookshelf1.getChapterId();
            hashMap.put("charterId", chapterId);
            String tableName = this.getTableName(bookId);
            String chapterName = chapterTablesMapper.getChapterName(bookshelf1.getBookId(), tableName, chapterId);
            hashMap.put("chapterName", chapterName);
            if (chapterName.equals(books.getNovelName())){
                hashMap.put("progress", "已读完");
            }else {
                hashMap.put("progress", "未读完" );
            }
            list.add(hashMap);
        }
            //防止缓存穿透
            if (list == null || list.isEmpty()) {
                //  缓存空结果，过期时间设短一点（1分钟）
                redisTemplate.opsForValue().set(key, null, 1, TimeUnit.MINUTES);
                return Collections.emptyList() ;
            }
            redisTemplate.opsForValue().set(key, list, 10, TimeUnit.MINUTES);
            return list;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 获取最近阅读
     *
     * @param userId
     * @return
     */
    @Override
    public List<Map<String, Object>> getBookreading(Long userId) {
        String key = Const.BOOKS_READING_DATA + ":" + userId;
        if(redisTemplate.hasKey(key)){
            Object value = redisTemplate.opsForValue().get(key);
            if (value == null) {
                // 缓存存在但值为null（已处理过穿透），直接返回空列表
                return Collections.emptyList();
            }
            return (List<Map<String, Object>>) value;
        }
        try {
            lock.lock();
            if(redisTemplate.hasKey(key)){
                Object value = redisTemplate.opsForValue().get(key);
                if (value == null) {
                    // 缓存存在但值为null（已处理过穿透），直接返回空列表
                    return Collections.emptyList();
                }
                return (List<Map<String, Object>>) value;
            }
            ArrayList<Map<String, Object>> list = new ArrayList<>();
            List<Bookshelf> bookshelf=bookshelfMapper.getBookreading(userId);

//n+1问题      后期优化
            for (Bookshelf bookshelf1 : bookshelf) {
                Integer bookId = bookshelf1.getBookId().intValue();
                if(bookId==null){
                    continue;
                }

                Books books = booksMapper.selectById(bookId);
                if (books == null) {
                    continue;
                }
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("bookId",bookId);
                hashMap.put("category", books.getCategory());
                hashMap.put("id", bookshelf1.getId());
                hashMap.put("name", books.getNovelName());
                hashMap.put("latestChapter", books.getLatestChapter());
                hashMap.put("author", books.getAuthor());
                hashMap.put("readTime",bookshelf1.getLastRead() );
                hashMap.put("updateTime", books.getUpdateTime());
                Long chapterId = bookshelf1.getChapterId();
                hashMap.put("charterId", chapterId);
                String tableName = this.getTableName(bookId);
                String chapterName = chapterTablesMapper.getChapterName(bookshelf1.getBookId(), tableName, chapterId);
                hashMap.put("chapterName", chapterName);
                if (chapterName.equals(books.getNovelName())){
                    hashMap.put("progress", "已读完");
                }else {
                    hashMap.put("progress", "未读完" );
                }
                list.add(hashMap);
            }
            //防止缓存穿透
            if (list == null || list.isEmpty()) {
                //  缓存空结果，过期时间设短一点（1分钟）
                redisTemplate.opsForValue().set(key, null, 1, TimeUnit.MINUTES);
                return Collections.emptyList() ;
            }
            redisTemplate.opsForValue().set(key, list, 10, TimeUnit.MINUTES);
            return list;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 删除书架
     *
     * @param ids
     * @param userId
     * @return
     */
    @Override
    public boolean deleteBooks(List<Long> ids, Long userId) {
        String key = Const.BOOKS_SHELF_DATA + ":" + userId;
        int deletedCount = bookshelfMapper.updateIsBookshelfByIdsAndUserId(ids, userId);
        if (deletedCount > 0) {
            redisTemplate.delete(key);
            return true;
        }
        return false;
    }

    /**
     * 删除流量历史
     * @param ids
     * @param userId
     * @return
     */
    @Override
    public boolean deleteReadingBooks(List<Long> ids, Long userId) {
        String key = Const.BOOKS_READING_DATA + ":" + userId;
        int deletedCount = bookshelfMapper.deleteReadingBooks(ids, userId);
        if (deletedCount > 0) {
            redisTemplate.delete(key);
            redisTemplate.delete(Const.BOOKS_SHELF_DATA + ":" + userId);
            return true;
        }
        return false;
    }

    /**
     * 获取书id对应的表名
     * @param bookId
     * @return
     */
    @NotNull
    public String getTableName(Integer bookId) {
        if(bookId <=0)
            throw new RuntimeException("参数错误");
//        获取分类类别
        String category =booksMapper.getCategoryById(bookId);
        if(category==null)
            throw new RuntimeException("系统错误");
//        获取章节表名
        String tableName =chapterTablesMapper.getChapterTableName(category);
        if(tableName==null)
            throw new RuntimeException("系统错误");
        return tableName;
    }
}
